#include "vtkFunctions.hpp"
#include "vtkFunctions_export.hpp"
#include "vtkConstants.hpp"

namespace hms::vtk
{


namespace internal
{

/* by delegating to a templated function, we get access to template parameters */
template<Uniformity isUniform, typename MeshType>
void writeConstantField(
	xml::XMLElement* fieldElem,
	const ConstantField<isUniform, MeshType>& field
){
	fieldElem->SetAttribute( nComponentsName, field.nComponents() );
	fieldElem->SetAttribute( "isUniform", static_cast<bool>(isUniform) );
	fieldElem->SetAttribute( "isFunction", false );

	if (isUniform)
		matrixToText( fieldElem , field.storage());
	else
		matrixToText( fieldElem , field.domainValues());
}

} // namespace internal



template<typename SolverType>
void writeConstantField(
	xml::XMLElement* parent,
	const SolverBase<SolverType>& solver,
	typename SolverBase<SolverType>::ConstantFieldName fieldName
){
	using S = SolverBase<SolverType>;
	using MeshType = typename S::MeshType;
	const ConstantFieldVar<MeshType>& fieldVar { solver.constantField(fieldName) };

	xml::XMLElement* fieldElem { parent->InsertNewChildElement(constChild) };
	fieldElem->SetAttribute( "Name",
		std::string{ magic_enum::enum_name( fieldName ) }.c_str()
	);

	std::visit( [&](const auto& field){
		internal::writeConstantField(fieldElem, field);
	}, fieldVar );
}


template<typename SolverType>
void writeConstantFields(
	xml::XMLNode* node,
	const SolverBase<SolverType>& solver
){
	using S = SolverBase<SolverType>;
	using ConstantFieldName = typename S::ConstantFieldName;

	xml::XMLElement* constantFields { createRootOrInsert(node, constNode) };

	for ( int i{0}; i < S::nConstantFields ; ++i ){
		ConstantFieldName fieldName { static_cast<ConstantFieldName>(i) };

		writeConstantField(
			constantFields,
			solver,
			fieldName
		);
	}
}

template<typename SolverType>
std::unique_ptr<xml::XMLDocument> constantFieldsToXML(
	const SolverBase<SolverType>& solver
){
	auto doc { std::make_unique<xml::XMLDocument>() };
	writeConstantFields( doc.get(), solver );
	return doc;
}


} // namespace hms::vtk
